import os

from flask import Blueprint, render_template, request, redirect, url_for, jsonify, session, g
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename

from apps.article.models import Article_type, Article
from apps.utils.uitl import upload_qiniu, delete_qiniu, send_message
from config import Config
from apps.user.models import User, Photo, AboutMe, MessageBoard
from extend import db, cache

user_bp = Blueprint('user', __name__, url_prefix='/user')

# 需要登录验证的url列表
required_login_list = [
    '/user/center',
    '/user/change',
    '/article/publish',
    '/user/upload_photo',
    '/user/photo_del',
    '/user/myphoto',
    '/article/add_comment',
    '/user/aboutme',
    # '/user/showabout'
]


# 自定义一个过滤器，用来在index首页转换二进制数据
@user_bp.app_template_filter('cdecode')
def content_decode(content):
    content = content.decode('utf8')
    return content[:200]  # 截断，只返回200个字符，在页面只显示这么多
    # return content


# 自定义aboutme界面用的过滤器
@user_bp.app_template_filter('cdecode1')
def content_decode(content):
    content = content.decode('utf8')
    return content


# 第一次发起请求时就会经过before_first_request
@user_bp.before_app_first_request
def befor_first_request():
    # 第一次请求时将定向到首页
    pass


# 访问验证,每次发起请求都会先经过before_request
@user_bp.before_app_request
def before_request():
    print('before_app_request')
    # 获取文章分类
    article_types = Article_type.query.all()
    g.article_types = article_types
    if request.path in required_login_list:
        id = session.get('uid')
        if not id:
            return render_template('user/login.html')
        else:
            user = User.query.get(id)
            # g 对象，本次请求的对象，全局属性，flask内置的
            # 生命周期-----》只在本次请求中有用，完成视图函数渲染后就自动回收了
            g.user = user


# 首页

# @cache.cached(timeout=50) # 给首页路由增加缓存时间
@user_bp.route('/')
def index():
    # 1.cookie的获取方式
    # uid = request.cookies.get('uid', None)
    # 2.session的获取方式，session底层默认获取，自动获取匹配

    # 获取页码数
    page = int(request.args.get('page', 1))
    # 获取文章列表
    pagination = Article.query.order_by(-Article.pdatetime).paginate(page=page, per_page=3)
    print(pagination.items)  # [<Article 4>, <Article 3>, <Article 2>]
    print(pagination.page)  # 当前的页码数
    print(pagination.prev_num)  # 当前页的前一个页码数
    print(pagination.next_num)  # 当前页的后一页的页码数
    print(pagination.has_next)  # True 是否有下一页
    print(pagination.has_prev)  # True 是否有上一页
    print(pagination.pages)  # 总共有几页
    print(pagination.total)  # 总的记录条数

    # 判断用户是否登录状态
    uid = session.get('uid')
    if uid:
        user = User.query.get(uid)
        return render_template('user/index.html', user=user, pagination=pagination)
    else:
        return render_template('user/index.html', pagination=pagination)


# 用户注册
@user_bp.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        confirmpassword = request.form.get('confirmpassword')
        phone = request.form.get('phone')
        email = request.form.get('email')
        if password == confirmpassword:
            # 注册用户
            user = User()
            user.username = username
            # 使用自带的函数实现加密：generate_password_hash
            user.password = generate_password_hash(password)
            # print(password)
            user.phone = phone
            user.email = email
            # 添加并提交
            db.session.add(user)
            db.session.commit()
            return redirect(url_for('user.index'))

    return render_template('user/register.html')


# 手机号码验证
@user_bp.route('/checkphone', methods=['GET', 'POST'])
def check_phone():
    phone = request.args.get('phone')
    user = User.query.filter(User.phone == phone).all()

    # code: 400 不能用    200 可以用
    if len(user) > 0:
        return jsonify(code=400, msg='此号码已被注册')
    else:
        return jsonify(code=200, msg='此号码可用')


# 用户登录
@user_bp.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        f = request.args.get('f')
        if f == '1':  # 用户名和密码登录
            username = request.form.get('username')
            password = request.form.get('password')
            users = User.query.filter(User.username == username).all()
            for user in users:
                # 如果flag=True表示匹配，否则密码不匹配
                flag = check_password_hash(user.password, password)
                if flag:
                    # 1.cookie实现登录机制
                    # response = redirect(url_for('user.index'))
                    # response.set_cookie('uid', str(user.id), max_age=1800)
                    # return response
                    # 2.session 实现机制，session当做字典使用
                    session['uid'] = user.id
                    return redirect(url_for('user.index'))
            else:
                return render_template('user/login.html', msg='用户名或者密码有误！')
        elif f == '2':  # 手机号码验证码登录
            phone = request.form.get('phone')
            code = request.form.get('code')
            # 先验证验证码
            # if session.get(phone) == code:
            # 改用redis缓存验证
            if cache.get(phone) == code:
            # 查询数据库
                user = User.query.filter(User.phone == phone).first()
                if user:
                    # 登录成功
                    session['uid'] = user.id
                    return redirect(url_for('user.index'))
                else:
                    return render_template('user/login.html', msg='你输入的账号不存在！')

            else:
                return render_template('user/login.html', msg='验证码输入有误！')

    return render_template('user/login.html')


# 发送短信息
@user_bp.route('sendmsg')
def send_message():
    phone = request.args.get('phone')

    # 补充验证手机号码是否已经注册过，查询数据库
    user = User.query.filter(User.phone == phone).first()
    if user:
        # 向网易云信平台发送验证码请求
        result = send_message(phone)
        if result.get('code') == 200:
            # session[phone] = result.get('obj')

            code=result.get('obj')
            # 改用redis缓存机制来记录短信验证码
            #cache.set(key,value,timeout=second)
            cache.set(phone,code,timeout=600)
            return jsonify(code=200, msg='短信发送成功！')
        else:
            return jsonify(code=200, msg='短信发送失败！')
    else:
        return jsonify(code=400, msg='此号码未注册，请先注册！')


# 用户退出
@user_bp.route('/logout')
def logout():
    # 1.cookie方式
    # response = redirect(url_for('user.index'))
    # response.delete_cookie('uid')
    # 2.session方式
    # del session['uid']
    # session.pop('uid')
    session.clear()
    return redirect(url_for('user.index'))


# 用户中心
@user_bp.route('/center')
def center():
    photos = Photo.query.filter(Photo.user_id == g.user.id).all()
    return render_template('user/center.html', user=g.user, photos=photos)


# 可以上传图片的扩展名列表
ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'bmp']


# 更改用户信息
@user_bp.route('/change', methods=['GET', 'POST'])
def user_change():
    # 为了使用户走这个路由的时候也是保持登录状态，这样才能知道是哪个用户在登录，
    # 所以也要把这个路由加入到钩子函数里去，这样就能使用g.user。
    # g 每次走完一个视图函数（路由）就会自动释放，所以上一g不能再使用，必须重新走钩子函数
    if request.method == 'POST':
        username = request.form.get('username')
        phone = request.form.get('phone')
        email = request.form.get('email')
        # 只要是文件就要使用request.files.get()方式获取
        icon = request.files.get('icon')
        print(icon, type(icon))  # FileStorage
        # 属性:filename 用户获取文件名字
        # 方法：save(保存路径)
        icon_name = icon.filename
        suffix = icon_name.rsplit('.')[-1]
        if suffix in ALLOWED_EXTENSIONS:
            # 用secure_filename()转换成安全的文件名
            # 保证文件名符合Python的命名规则
            icon_name = secure_filename(icon_name)
            file_path = os.path.join(Config.UPLOAD_ICON_DIR, icon_name)
            print('文件路径-====》', file_path)
            icon.save(file_path)
            # 本地保存成功
            # 设置数据库保存路径
            user = g.user
            user.username = username
            user.phone = phone
            user.email = email
            # 提前准备path,相对路径
            path = 'upload/icon/'
            user.icon = os.path.join(path, icon_name)
            db.session.commit()
            return redirect(url_for('user.user_change'))
        else:
            return render_template('user/center.html', user=g.user, msg='文件格式必须是jpg、jpeg、png、gif、bmp格式！')
        # # 查询一下手机号码
        # users = User.query.all()
        # for user in users:
        #     if user.phone == phone:
        #         # 说明此号码已经在数据库中出现过了
        #         return render_template('user/center.html', user=g.user, msg='此号码已经被注册过了！')

        # 2.用ajax异步请求，上面已经定义好一个路由了直接用

    return render_template('user/center.html', user=g.user)


# 上传图片
@user_bp.route('/upload_photo', methods=['GET', 'POST'])
def upload_photo():
    # 获取上传的内容
    photo = request.files.get('photo')  # FileStorage
    # photo.filename获取文件名
    # photo.save(path)存储到本地

    # 使用工具封装方法
    ret, info = upload_qiniu(photo)
    if info.status_code == 200:
        photo = Photo()
        photo.photo_name = ret['key']
        photo.user_id = g.user.id
        db.session.add(photo)
        db.session.commit()
        return '上传成功'
    else:
        return '上传失败'


# 我的相册
@user_bp.route('/myphoto')
def myphoto():
    page = int(request.args.get('page', 1))
    # 分页操作
    photos = Photo.query.paginate(page=page, per_page=3)
    user_id = session.get('uid')
    user = None
    if user_id:
        user = User.query.get(user_id)

    return render_template('user/myphoto.html', photos=photos, user=user)


# 删除图片
@user_bp.route('/photo_del')
def photo_del():
    photo_id = request.args.get('pid')
    photo = Photo.query.get(photo_id)
    filename = photo.photo_name
    # 删除七牛云存储上的图片
    info = delete_qiniu(filename)
    if info.status_code == 200:
        # 删除数据库的内容
        db.session.delete(photo)
        db.commit()
        return redirect(url_for('user.center'))
    else:
        referer = request.headers.get('referer', url_for('user.index'))
        return render_template('500.html', error_msg='删除图片失败！', referer=referer)


# 错误页面
@user_bp.route('/error')
def error():
    referer = request.headers.get('referer', url_for('user.index'))
    return render_template('500.html', error_msg='删除图片失败！', referer=referer)


# 更改用户介绍
@user_bp.route('/aboutme', methods=['GET', 'POST'])
def about_me():

    content = request.form.get('about')

    try:
        aboutme = AboutMe()
        aboutme.content = content.encode('utf-8')
        aboutme.user_id = g.user.id
        db.session.add(aboutme)
        db.session.commit()
    except Exception as err:
        return redirect(url_for('user.center'))
    else:
        return render_template('user/aboutme.html', user=g.user)


@user_bp.route('/showabout')
def show_about():
    return render_template('index.html')
    # return render_template('user/aboutme.html', user=g.user)



# 留言板
@user_bp.route('/board', methods=['GET', 'POST'])
def show_board():
    uid = session.get('uid')
    user = None
    if uid:
        user = User.query.get(uid)

    # 查询所有的内容
    page = int(request.args.get('page', 1))
    boards = MessageBoard.query.order_by(-MessageBoard.mdatetime).paginate(page=page, per_page=5)
    if request.method == 'POST':
        content = request.form.get('board')
        # 添加留言内容
        msg_board = MessageBoard()
        msg_board.content = content
        if uid:
            msg_board.user_id = uid

        db.session.add(msg_board)
        db.session.commit()
        return redirect(url_for('user.show_board'))

    return render_template('user/msg_board.html', user=user, boards=boards)


# 删除留言
@user_bp.route('/deleteboard')
def delete_board():
    message_id = request.args.get('bid')
    if message_id:
        message=MessageBoard.query.get(message_id)
        db.session.delete(message)
        db.session.commit()

    return redirect(url_for('user.center'))
